home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / DevTools / eText5 / Source / eTFileLink.subproj / eTRTFDFileLink.m < prev    next >
Encoding:
Text File  |  1994-10-24  |  5.2 KB  |  139 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //    FILENAME:    eTRTFDFileLink.h 
  3. //    SUMMARY:    Implementation of an RTFD inclusion handler
  4. //    SUPERCLASS:    eTFileLink:eTImage:Object
  5. //    INTERFACE:    None
  6. //    PROTOCOLS:    None added
  7. //    AUTHOR:        Rohit Khare
  8. //    COPYRIGHT:    (c) 1994 California Institure of Technology, eText Project
  9. ///////////////////////////////////////////////////////////////////////////////
  10. //    IMPLEMENTATION COMMENTS
  11. //        Okay: here are the facts of life about NeXT's lousy RTFD implementation
  12. //    (trust me, I know, I know the Text object every which way except from the
  13. //    inside... grrr). It goes: 
  14. //        <space char>string<spacechar>\width<inTwips>\height<inTwips>\n}
  15. //    (the string spec is such that you have to read it in two passes -- that's
  16. //    why I always prefix a string by the length. (e.g. NeXT fails on a file
  17. //    named "\width960"))
  18. //        
  19. //    OK, once you have the string, you have a relative filename component. Where
  20. //    do we get the root filename component? We assume that we can reach out
  21. //    and access() [[[view etDoc] docInfo] docPath]. 
  22. //    
  23. //    OK, now we have a fully-qualified absolute pathname. If it's a TIFF image,
  24. //    we want to promote self to be an eTImage object encapsulating that file.
  25. //    otherwise we want to be an eTFileLink.
  26. //
  27. //    THERE ARE NO eTRTFDFileLinks IN THE SYSTEM AFTER readRichText: !!!!
  28. //        All such instances are "promoted" by redirecting their isa pointer
  29. //    Thus, when the file is written out, RTFD-objects will be implicitly
  30. //    promoted to first-class eText objects. 
  31. //
  32. //    As an exercise for the reader: With enough cojones, it should be possible
  33. //    to write a generic mutator to eTImage-derived objects; just make sure that
  34. //    this object has as many bytes of storage as the larget morph target. Then
  35. //    you could _automatically_ morph a .snd inclusion into an eTAudio :)
  36. ///////////////////////////////////////////////////////////////////////////////
  37. //    HISTORY
  38. //    07/23/94:    Created. First actual implementation.
  39. ///////////////////////////////////////////////////////////////////////////////
  40.  
  41. #import "eTRTFDFileLink.h"
  42.  
  43. @implementation eTRTFDFileLink
  44. + toolAwake: theApp
  45. {
  46.     [theApp   registerAnnotation: [eTRTFDFileLink class] 
  47.                             name: "eTRTFDFileLink"
  48.                     RTFDirective: "NeXTGraphic"
  49.                        menuLabel: NULL
  50.                          menuKey: '\0'
  51.                         menuIcon: (NXImage *) nil];
  52.     return self;
  53. }
  54. - readRichText:(NXStream *) stream forView:view
  55. {
  56.     const char *const * types;
  57.     char *ext;
  58.     NXAtom    localPath,rootPath;
  59.     char    buffer[MAXPATHLEN],ch;
  60.     int        height=0, width=0,i=0;
  61.     char    *tmp;
  62.     BOOL    foundImage=NO;
  63.     
  64.     // we first have to do this because this silly hack-class of ours can't
  65.     // call [super readRichText:...] (this code is in eTImage.m)
  66.     if (!etDoc || !theText) {
  67.         theText = view;
  68.         etDoc = [theText etDoc];
  69.         [etDoc registerNotification:self];
  70.     }
  71.     // first fill in the buffer with all the characters up to and including \n
  72.     while ((i < MAXPATHLEN) && ((ch = NXGetc(stream)) != '\n')) {
  73.         buffer[i++] = ch;
  74.     }
  75.     buffer[i] = 0;    
  76.     // now work backward to get height.
  77.     tmp = rindex(buffer,'\\');
  78.     if (tmp && !strncmp(tmp, "\\height",7)) {
  79.         //we have a valid \height entry beginning at tmp
  80.         sscanf(tmp+7,"%d",&height);
  81.         // now nullify the \ so we can go backwards to \width
  82.         *tmp = 0;
  83.     }
  84.     // now work backward to get width.
  85.     tmp = rindex(buffer,'\\');
  86.     if (tmp && !strncmp(tmp, "\\width",6)) {
  87.         //we have a valid \height entry beginning at tmp
  88.         sscanf(tmp+6,"%d",&width);
  89.         // now nullify the \ so we can go backwards to the string
  90.         *tmp = 0;
  91.         // and also consume the space character separating string from \width
  92.         *(tmp - 1) = 0;
  93.     }
  94.     
  95.     // skip the leading space -- is there one?
  96.     tmp = buffer;
  97.     if (*tmp == ' ') tmp++;
  98.     localPath = NXUniqueString(tmp);
  99.     rootPath = [[[view etDoc] docInfo] docPath];
  100.     sprintf(buffer, "%s/%s", rootPath, localPath);
  101.     
  102.     // OK, now what? We have valid data.
  103.     //NXLogError("\\NeXTGraphic got \"%s\" h:%d w:%d in \"%s\"", 
  104.     //            localPath, height, width, rootPath); 
  105.         
  106.     tmp = rindex(buffer,'/'); //get the extension of the basename.
  107.     tmp = rindex(tmp,'.');
  108.     if (tmp && *(++tmp)) {
  109.         // ext is now a pointer to the extension of buffer, if there is one.
  110.         ext = NXUniqueString(tmp); // ext of basename
  111.         types = [NXImage imageFileTypes];
  112.         for(i=0; (types[i] && !foundImage); i++)
  113.             if (!strcmp(ext,types[i])) foundImage = YES;
  114.     }
  115.     if (foundImage) {
  116.         // If the target file can be viewed as imageable data, we should
  117.         // "morph" into an eTImage instance based on that file.
  118.         // The code that eTImage would execute in this situation:
  119.         //        1) create an imageComponent
  120.         //        2) [self setImageComponent] 
  121.         self->isa = [eTImage class]; // assumes that we are a subclass of it
  122.         [self setImageComponent: [[[eTImageComponent alloc] 
  123.                 initInDoc:etDoc linked:NO]
  124.                 readComponentFromPath:buffer]];
  125.     } else {
  126.         // else we need to init etFileComponent _and_ attempt to initialize
  127.         // eTImageComponent from buffer.tiff.
  128.         self->isa = [eTFileLink class];
  129.         
  130.         etFileComponent = [[[eTComponent alloc] initInDoc:etDoc linked:NO]
  131.                             readComponentFromPath:buffer];
  132.         strcat(buffer,".tiff"); //this is NeXT's default behavior
  133.         [self setImageComponent: [[[eTImageComponent alloc] 
  134.                 initInDoc:etDoc linked:NO]
  135.                 readComponentFromPath:buffer]]    ;
  136.     }
  137.     return self;
  138. }
  139. @end